package com.ticket.system.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.ticket.common.constant.PerformConstants;
import com.ticket.common.exception.ServiceException;
import com.ticket.system.domain.*;
import com.ticket.common.exception.base.BaseException;
import com.ticket.common.utils.poi.ExcelUtil;
import com.ticket.system.domain.YanchuConsumeRecord;
import com.ticket.system.domain.YanchuOrder;
import com.ticket.system.domain.YanchuRefundOrder;
import com.ticket.system.domain.vo.BatchExportVO;
import com.ticket.system.domain.vo.CardExportVO;
import com.ticket.system.domain.vo.CardVo;
import com.ticket.system.mapper.YanchuConsumeRecordMapper;
import org.apache.commons.collections4.CollectionUtils;
import com.ticket.system.mapper.YanchuMovieBatchMapper;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ticket.system.mapper.YanchuMovieCardMapper;
import com.ticket.system.service.IYanchuMovieCardService;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;

/**
 * 观演卡数据Service业务层处理
 * 
 * @author ruoyi
 * @date 2023-12-12
 */
@Service
public class YanchuMovieCardServiceImpl implements IYanchuMovieCardService 
{
    private static final Logger logger = LoggerFactory.getLogger(YanchuMovieCardServiceImpl.class);
    @Autowired
    private YanchuMovieCardMapper yanchuMovieCardMapper;
    @Autowired
    private YanchuConsumeRecordMapper yanchuConsumeRecordMapper;
    @Autowired
    private YanchuMovieBatchMapper yanchuMovieBatchMapper;
    /**
     * 查询观演卡数据
     * 
     * @param id 观演卡数据主键
     * @return 观演卡数据
     */
    @Override
    public YanchuMovieCard selectYanchuMovieCardById(Long id)
    {
        return yanchuMovieCardMapper.selectYanchuMovieCardById(id);
    }

    /**
     * 查询观演卡数据列表
     * 
     * @param yanchuMovieCard 观演卡数据
     * @return 观演卡数据
     */
    @Override
    public List<YanchuMovieCard> selectYanchuMovieCardList(YanchuMovieCard yanchuMovieCard)
    {
        return yanchuMovieCardMapper.selectYanchuMovieCardList(yanchuMovieCard);
    }

    /**
     * 新增观演卡数据
     * 
     * @param yanchuMovieCard 观演卡数据
     * @return 结果
     */
    @Override
    public int insertYanchuMovieCard(YanchuMovieCard yanchuMovieCard)
    {
        return yanchuMovieCardMapper.insertYanchuMovieCard(yanchuMovieCard);
    }

    /**
     * 修改观演卡数据
     * 
     * @param yanchuMovieCard 观演卡数据
     * @return 结果
     */
    @Override
    public int updateYanchuMovieCard(YanchuMovieCard yanchuMovieCard)
    {
        return yanchuMovieCardMapper.updateYanchuMovieCard(yanchuMovieCard);
    }

    /**
     * 添加观演卡消费记录
     *
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int consume(YanchuOrder yanchuOrder, CardVo cardVo)
    {
        int count = yanchuMovieCardMapper.consume(cardVo.getId(),yanchuOrder.getUserId(), cardVo.getAmount());

        if(count > 0){
            YanchuMovieCard card = yanchuMovieCardMapper.selectYanchuMovieCardById(cardVo.getId());
            if(null == card){
                throw new ServiceException("观演卡信息不正确!");
            }
            YanchuConsumeRecord consumeRecord = new YanchuConsumeRecord();
            consumeRecord.setAmount(cardVo.getAmount().negate());
            consumeRecord.setCardNum(cardVo.getCardNum());
            consumeRecord.setOrderId(yanchuOrder.getId());
            consumeRecord.setConType(PerformConstants.CONSUME_TYPE_CARD);
            consumeRecord.setCardType(PerformConstants.CARD_TYPE_CARD);
            consumeRecord.setOrderId(yanchuOrder.getId());
            consumeRecord.setBalance(card.getBalance());
            consumeRecord.setStatus(PerformConstants.CARD_STATUS_SUCCESS);
            consumeRecord.setBindId(yanchuOrder.getUserId());
            consumeRecord.setOperaId(yanchuOrder.getOperaId());
            consumeRecord.setCreatTime(new Date());
            consumeRecord.setIsDel(0);
            yanchuConsumeRecordMapper.insertYanchuConsumeRecord(consumeRecord);
        }
        return count;
    }

    /**
     * 按观演卡消费记录退观演卡
     * cardAmt 退款金额
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int refundByRecord(YanchuConsumeRecord record,BigDecimal cardAmt){
        logger.info("refundByRecord amt:{} cardAmt:{}",record.getAmount(),cardAmt);
        BigDecimal amt = record.getAmount().negate();//消费金额
        if(null != cardAmt && cardAmt.compareTo(BigDecimal.ZERO)>0){//退款金额
            amt = cardAmt;
        }else if(record.getRefundAmt().compareTo(BigDecimal.ZERO)>0){
            amt = amt.subtract(record.getRefundAmt());
            if(amt.compareTo(BigDecimal.ZERO)<=0){
                return 0;
            }
        }

        logger.info("refundByRecord cardNum:{} amt:{} userId:{} cardAmt:{}",record.getCardNum(),amt,record.getBindId(),cardAmt);
        int count = yanchuMovieCardMapper.refund(record.getCardNum(), amt, record.getBindId());
        if(count > 0){
            YanchuMovieCard yanchuMovieCard = yanchuMovieCardMapper.selectCardByCardNum(record.getCardNum());
            if(null == yanchuMovieCard){
                throw new ServiceException("获取观演卡信息失败");
            }
            YanchuConsumeRecord consumeRecord = new YanchuConsumeRecord();
            consumeRecord.setAmount(amt);
            consumeRecord.setOrderId(record.getOrderId());
            consumeRecord.setConType(PerformConstants.REFUND_TYPE_CARD);
            consumeRecord.setCardType(PerformConstants.CARD_TYPE_CARD);
            consumeRecord.setBalance(yanchuMovieCard.getBalance());
            consumeRecord.setStatus(PerformConstants.CARD_STATUS_SUCCESS);
            consumeRecord.setOperaId(record.getOperaId());
            consumeRecord.setBindId(record.getBindId());
            consumeRecord.setCreatTime(new Date());
            consumeRecord.setCardNum(record.getCardNum());
            consumeRecord.setIsDel(0);
            yanchuConsumeRecordMapper.insertYanchuConsumeRecord(consumeRecord);

            record.setRefundAmt(record.getRefundAmt().add(amt));
            if(record.getRefundAmt().compareTo(record.getAmount().negate())>=0){
                record.setStatus(PerformConstants.CARD_STATUS_REFUND);
            }else{
                record.setStatus(PerformConstants.CARD_STATUS_REFUND_PART);
            }
            yanchuConsumeRecordMapper.updateYanchuConsumeRecord(record);
        }
        return count;
    }

    /**
     * 部分退款
     * @param refundOrder
     * @param yanchuOrder
     * @return
     */
    public int refund(YanchuRefundOrder refundOrder,YanchuOrder yanchuOrder,BigDecimal cardAmt){
        List<YanchuConsumeRecord> list = yanchuConsumeRecordMapper.selectRecordList(yanchuOrder.getId(),yanchuOrder.getUserId());
        if(CollectionUtils.isEmpty(list)){
            throw new ServiceException("暂无可退观演卡余额");
        }
        BigDecimal totalAmt = cardAmt;
        BigDecimal leftAmt = null;
        int count = 0;
        for(YanchuConsumeRecord record:list){
            leftAmt = record.getAmount().negate().subtract(record.getRefundAmt());//剩余可退
            if(leftAmt.compareTo(BigDecimal.ZERO) <= 0){
                continue;
            }
            //剩余可退
            if(leftAmt.compareTo(totalAmt) >= 0){
                count += refundByRecord(record,totalAmt);
                break;
            }else{
                count += refundByRecord(record,leftAmt);
                totalAmt = totalAmt.subtract(leftAmt);
            }
        }
        return count;
    }

    /**
     * 批量删除观演卡数据
     * 
     * @param ids 需要删除的观演卡数据主键
     * @return 结果
     */
    @Override
    public int deleteYanchuMovieCardByIds(Long[] ids)
    {
        return yanchuMovieCardMapper.deleteYanchuMovieCardByIds(ids);
    }

    /**
     * 删除观演卡数据信息
     * 
     * @param id 观演卡数据主键
     * @return 结果
     */
    @Override
    public int deleteYanchuMovieCardById(Long id)
    {
        return yanchuMovieCardMapper.deleteYanchuMovieCardById(id);
    }

    /**
     * pc获取卡列表
     *
     * @param amount
     * @param cardNum
     * @param keyName
     * @return
     */
    @Override
    public List<YanchuMovieCard> selectYanchuMovieCardByList(Long batchId,String cardNum,String amount,String keyName,Integer status) {
        return yanchuMovieCardMapper.selectYanchuMovieCardByList(batchId,cardNum, amount, keyName,status);
    }

    /**
     * 导出观演卡
     *
     * @param carIds
     * @param response
     */
    @Override
    public void export(List<Long> carIds, HttpServletResponse response) {
        if (CollectionUtils.isEmpty(carIds)){
            throw new BaseException("不存在观演卡");
        }
        BatchExportVO vo = yanchuMovieCardMapper.selectCardsByCardIds(carIds);
        //生成表头
        List<String> headExcel = new ArrayList<>();
        headExcel.add("卡号");
        headExcel.add("卡面金额");
        headExcel.add("密码(加涂层)");
        HSSFWorkbook wb = new HSSFWorkbook();
        //标题设置样式
        HSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        HSSFFont font = wb.createFont();
        font.setFontHeightInPoints((short) 10);            // 字体高度
        font.setColor(HSSFFont.COLOR_NORMAL);                // 字体颜色
        font.setBold(true);  //加粗
        cellStyle.setFont(font);

        //表头设置样式
        HSSFCellStyle cellStyle1 = wb.createCellStyle();
        cellStyle1.setAlignment(HorizontalAlignment.CENTER);
        HSSFFont font1 = wb.createFont();
        font1.setFontHeightInPoints((short) 10);            // 字体高度
        font1.setColor(HSSFFont.COLOR_NORMAL);                // 字体颜色
        cellStyle1.setFont(font);

        String sheetName = vo.getBatchName();
        HSSFSheet sheet = wb.createSheet(sheetName);
        sheet.setColumnWidth(0,23*256);
        //设置标题
        CellRangeAddress callRangeAddress = new CellRangeAddress(0, 0, 0, 2);//起始行,结束行,起始列,结束列
        //加载合并单元格
        sheet.addMergedRegion(callRangeAddress);
        Row row = sheet.createRow(0);
        Cell cell = row.createCell(0);
        cell.setCellValue("观演卡制卡数据");
        cell.setCellStyle(cellStyle);
        //设置表头
        Row row1 = sheet.createRow(1);
        for (int i1 = 0; i1 < headExcel.size(); i1++) {
            Cell cell1 = row1.createCell(i1);
            cell1.setCellValue(headExcel.get(i1));
            cell1.setCellStyle(cellStyle1);
        }
        List<CardExportVO> cards = vo.getVos();
        if (!CollectionUtils.isEmpty(cards)){
            for (int j = 0; j < cards.size(); j++) {
                Row row2 = sheet.createRow(j+2);
                Cell cell1 = row2.createCell(0);
                cell1.setCellValue(cards.get(j).getCardNum());
                Cell cell2 = row2.createCell(1);
                cell2.setCellValue(cards.get(j).getAmount().concat("元"));
                Cell cell3 = row2.createCell(2);
                cell3.setCellValue(cards.get(j).getCardPasswoed());
            }
        }
         ExcelUtil.exportExcel2Browser(response,"观演卡数据.xls",wb);
    }

    /**
     * 小程序登录用户绑定观演卡
     *
     * @param cardNum
     * @param cardPasswoed
     * @param userName
     * @param userId
     * @param phonenumber
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int bindMovie(String cardNum, String cardPasswoed, String userName, Long userId, String phonenumber) {
        List<YanchuMovieCard> cards = yanchuMovieCardMapper.selectYanchuMovieCardList(new YanchuMovieCard(cardNum));
        if (CollectionUtils.isEmpty(cards) || yanchuMovieCardMapper.checkValidTime(cardNum)){
            throw new BaseException("该观演卡不存在,请重新输入!");
        }
        if (null == cards.get(0).getActiveId()){
            throw new BaseException("该观演卡未激活,暂无法绑定");
        }
        if (!cardPasswoed.equals(cards.get(0).getCardPasswoed())){
            throw new BaseException("密码不正确,请重新输入");
        }
        if (null != cards.get(0).getBindId()){
            throw new BaseException("该观演卡已绑定");
        }
        //修改批次绑定数
        yanchuMovieBatchMapper.updateBindNum(cards.get(0).getBatchId());
        //绑定观演卡
        return yanchuMovieCardMapper.updateBindMovieCard(cardNum,userId,userName,phonenumber);
    }

    /**
     * 小程序返回用户观演卡数据
     *
     * @param userId
     * @param type
     * @return
     */
    @Override
    public List<YanchuMovieCard> mobileCardList(Long userId, Integer type) {
        return yanchuMovieCardMapper.mobileCardList(userId,type);
    }
}
